/**
* This file is part of OntoCompoFramework
*
* Copyright (C) 2011 -  Christian Brel
*
* @author   Main    Christian Brel
**/
package ontocompo.ui.selection;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Observable;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;

import com.mockobjects.constraint.IsInstanceOf;

import ontocompo.ui.screenmanagement.Screen;
import ontocompo.ui.screenmanagement.ScreenConsumer;
import ontocompo.ui.screenmanagement.ScreenInfo;
import ontocompo.ui.screenmanagement.ScreenPossibilities;


import static java.lang.Math.PI;

public class SelectionTools extends Observable implements ScreenConsumer {

	/** ToolBar Content **/
	private JPanel toolsContainer;
	private JPanel globalActionContainer;
	private JPanel selectionDetailsContainer;
	private JPanel extractionDetailsContainer;
	private JPanel guideSelectionPanel;
	private JCheckBox guideCheckBox;
	private JComboBox guideTypesList;
	
	JPanel layoutExtensionPanel;
	
	// private JComboBox screenComboBox;
	private ScreenPossibilities forExtraction;
	/** ToolBar Content **/
	
	private JPanel selectionToolsBar;
	
	// pour les boutons
	ImageIcon [] icons = new ImageIcon[8];
	ImageIcon [] iconsSelected = new ImageIcon[8];
	String[] directionName = {"left", "topleft", "top", "topright", "right", "bottomright", "bottom", "bottomleft"};
	// int[][] positions = {{1,2,3}, {0,-1,4}, {7,6,5}};
	JToggleButton [] directions ;
	double [] angles = {PI, -PI*3/4, -PI/2, -PI/4, 0, PI/4, PI/2, 3*PI/4};
	final int radius = 130;
	final int diametre = radius*2;
	final int imagesize = 80;
	
	
	
	public SelectionTools() {
		this.init();
	}
	
	public JComponent getToolBarFrame() {
		
		return this.selectionToolsBar;
	}
	
	private void init() {
		
		this.selectionToolsBar = new JPanel();
		selectionToolsBar.setLayout(new BoxLayout(selectionToolsBar, BoxLayout.Y_AXIS));
//		Dimension d = new Dimension(700, 700);
//		selectionToolsBar.setMaximumSize(d);
//		selectionToolsBar.setPreferredSize(d);
//		selectionToolsBar.setSize(d);
		
		JPanel headPanel = new JPanel();
		// headPanel.setLayout(new BoxLayout(headPanel, BoxLayout.X_AXIS));
		headPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
		Dimension d = new Dimension(700, 100);
		headPanel.setMaximumSize(d);
		headPanel.setPreferredSize(d);
		headPanel.setSize(d);

		this.guideSelectionPanel = new JPanel();
		d = new Dimension(170, 80);
		guideSelectionPanel.setMaximumSize(d);
		guideSelectionPanel.setPreferredSize(d);
		guideSelectionPanel.setSize(d);
		// this.guideSelectionPanel.setLayout(new BoxLayout(this.guideSelectionPanel, BoxLayout.X_AXIS));
		this.guideSelectionPanel.setBorder(BorderFactory.createTitledBorder("Guided Selection"));
		guideSelectionPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
//		guideSelectionPanel.setMaximumSize(new Dimension(75, guideSelectionPanel.getHeight()));
		guideSelectionPanel.add(Box.createHorizontalGlue());
		
		this.guideCheckBox = new JCheckBox("Enable help selection");
		this.guideSelectionPanel.add(this.guideCheckBox);
		
//		String[] guideTypes = { "Complete help", "Task type selection help", "Functionaly type selection help", "Layout type selection help" };
		GuideType[] guideTypes = { GuideType.COMPLETE_HELP, GuideType.TASK_HELP, GuideType.FUNCT_HELP, GuideType.LAYOUT_HELP };
		this.guideTypesList = new JComboBox(guideTypes);
		this.guideTypesList.setSelectedIndex(0);
		this.guideTypesList.setEnabled(false);
		this.guideTypesList.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				JComboBox guideTypesList = (JComboBox)e.getSource();
				GuideType guideType = (GuideType)guideTypesList.getSelectedItem();
		        changeGuideType(guideType);
			}
			
		});
		d = new Dimension(150, 20);
		guideTypesList.setMaximumSize(d);
		guideTypesList.setPreferredSize(d);
		guideTypesList.setSize(d);
		this.guideSelectionPanel.add(this.guideTypesList);
		guideSelectionPanel.add(Box.createHorizontalGlue());
		headPanel.add(this.guideSelectionPanel);
		
		selectionToolsBar.add(headPanel);
//		selectionToolsBar.add(Box.createVerticalStrut(5));
//		selectionToolsBar.add(guideSelectionPanel);
		
		this.toolsContainer = new JPanel();
		this.toolsContainer.setLayout(new BoxLayout(this.toolsContainer, BoxLayout.X_AXIS));
		this.toolsContainer.setBorder(BorderFactory.createLineBorder(Color.BLACK));
//		this.toolsContainer.setMaximumSize(new Dimension(150, this.toolsContainer.getHeight()));
		
		this.globalActionContainer = new JPanel();
//		this.globalActionContainer.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
		this.globalActionContainer.setLayout(new BoxLayout(this.globalActionContainer, BoxLayout.X_AXIS));

//		this.globalActionContainer.setMaximumSize(new Dimension(150, this.globalActionContainer.getHeight()));
		
		ImageIcon icon = new ImageIcon("icons/selectAll.png");
		JButton selectAll = new JButton(icon);
		selectAll.setToolTipText("Select All");
		selectAll.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				selectAll();
			}
			
		});
		this.globalActionContainer.add(Box.createHorizontalStrut(2));
		this.globalActionContainer.add(selectAll);
		
		icon = new ImageIcon("icons/selectNone.png");
		JButton clearSelection = new JButton(icon);
		clearSelection.setToolTipText("Clear Selection");
		clearSelection.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				clearSelection();
			}
			
		});
		this.globalActionContainer.add(Box.createHorizontalStrut(2));
		this.globalActionContainer.add(clearSelection);
		
//		JButton undoSelection = new JButton("Undo");
//		this.globalActionContainer.add(undoSelection);
//		
//		JButton redoSelection = new JButton("Redo");
//		this.globalActionContainer.add(redoSelection);
		
		this.toolsContainer.add(this.globalActionContainer);
		
		JPanel selectionTypePanel = new JPanel();
		d = new Dimension(200, 80);
		selectionTypePanel.setMaximumSize(d);
		selectionTypePanel.setPreferredSize(d);
		selectionTypePanel.setSize(d);
		// selectionTypePanel.setLayout(new BoxLayout(selectionTypePanel, BoxLayout.Y_AXIS));
		
		JLabel selectionTypeLabel = new JLabel("Selection Type:");
		selectionTypeLabel.setHorizontalTextPosition(SwingConstants.CENTER);
		d = new Dimension(150, 30);
		selectionTypeLabel.setMaximumSize(d);
		selectionTypeLabel.setPreferredSize(d);
		selectionTypeLabel.setSize(d);
		selectionTypePanel.add(selectionTypeLabel);
		
		//String[] selectionTypes = { "Replace the selection", "Add to selection", "Remove from selection", "Intersection with selection" };
		SelectionType[] selectionTypes = { SelectionType.REPLACE_SELECTION, SelectionType.ADD_SELECTION, SelectionType.REMOVE_SELECTION, SelectionType.INTERSECTION_SELECTION };
		JComboBox selectionTypesList = new JComboBox(selectionTypes);
		selectionTypesList.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				JComboBox selectionTypeList = (JComboBox)e.getSource();
				SelectionType selectionType = (SelectionType)selectionTypeList.getSelectedItem();
		        changeSelectionType(selectionType);
			}
			
		});
		selectionTypesList.setSelectedIndex(1);
		selectionTypePanel.add(selectionTypesList);
		
		this.toolsContainer.add(Box.createHorizontalStrut(2));
		this.toolsContainer.add(selectionTypePanel);
		
//		selectionToolsBar.add(Box.createVerticalStrut(5));
//		selectionToolsBar.add(this.toolsContainer);
//		headPanel.add(Box.createHorizontalStrut(5));
		headPanel.add(this.toolsContainer);
//		headPanel.add(Box.createHorizontalGlue());
//		headPanel.add(Box.createHorizontalStrut(5));
		
		this.selectionDetailsContainer = new JPanel();
		this.selectionDetailsContainer.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
		this.selectionDetailsContainer.setLayout(new BoxLayout(this.selectionDetailsContainer, BoxLayout.X_AXIS));
		// un petit hack pour positionner correctement... reprendre la construction tranquillement...
		
		d = new Dimension(700, 525);
		selectionDetailsContainer.setMaximumSize(d);
		selectionDetailsContainer.setPreferredSize(d);
		selectionDetailsContainer.setSize(d);
		
		layoutExtensionPanel =  new JPanel();
		layoutExtensionPanel.setBorder(BorderFactory.createTitledBorder("Layout Extension"));
		layoutExtensionPanel.setLayout(new BoxLayout(layoutExtensionPanel, BoxLayout.Y_AXIS));
		
		JPanel positionsPanel = new JPanel() {
			@Override
			public void paint(Graphics g)
			{
				Graphics2D g2d = (Graphics2D) g;
				g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

				g2d.setStroke(new BasicStroke(2f));
				super.paint(g);
			}
		};

		positionsPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
		positionsPanel.setLayout(null);
		positionsPanel.setSize(diametre+imagesize+10, diametre+imagesize+10);
		
		positionsPanel.setMaximumSize(positionsPanel.getSize());
		positionsPanel.setPreferredSize(positionsPanel.getSize());
		positionsPanel.setMinimumSize(positionsPanel.getSize());
		
		final Color transColor = new Color(0,0,0,0);
		directions = new JToggleButton[8];
		double cx = positionsPanel.getWidth()/2;
		double cy = positionsPanel.getHeight()/2;
		for(int i = 0; i < directions.length; i++)
		{
			icons[i] = new ImageIcon("fleches/basic/arrow0"+i+".png");
			iconsSelected[i] = new ImageIcon("fleches/selected/arrow0"+i+".png");
			directions[i] = new JToggleButton(icons[i]) {
				protected void paintComponent(Graphics g)
				{
					Graphics2D g2d = (Graphics2D) g;
					g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

					g2d.setStroke(new BasicStroke(2f));
					if (isSelected())
					{
						getSelectedIcon().paintIcon(this, g2d, 0, 0);
					}
					else getIcon().paintIcon(this, g2d, 0, 0);
				}
			};
			directions[i].setFocusable(false);
			directions[i].setOpaque(false);
			directions[i].setBackground(transColor);
			directions[i].setSelectedIcon(iconsSelected[i]);
			// set RolloverIcon + quand select ... modifier paintComponent ci-dessus
			
			directions[i].setBorderPainted(false);
			
			double x = cx+Math.cos(angles[i])*radius-imagesize/2;
			double y = cy+Math.sin(angles[i])*radius-imagesize/2;
			
			// positionnement absolue
			directions[i].setLocation((int) x, (int) y);
			directions[i].setSize(directions[i].getPreferredSize());
			positionsPanel.add(directions[i]);
		}
		
		layoutExtensionPanel.add(positionsPanel);
		
		JPanel positionsDetails = new JPanel();
		positionsDetails.setLayout(new BoxLayout(positionsDetails, BoxLayout.Y_AXIS));
		positionsDetails.add(new JLabel("Apply to:"));
		positionsDetails.setMaximumSize(new Dimension(400, 200));
		positionsDetails.setMinimumSize(new Dimension(400, 200));
		
		final JRadioButton firstSelected = new JRadioButton("First selected element");
		firstSelected.setSelected(true);
		final JRadioButton lastSelected = new JRadioButton("Last selected element");
		final JRadioButton allSelected = new JRadioButton("All selection");
		
	    ButtonGroup possibilitiesGroup = new ButtonGroup();
	    possibilitiesGroup.add(firstSelected);
	    possibilitiesGroup.add(lastSelected);
	    possibilitiesGroup.add(allSelected);
	    
	    positionsDetails.add(firstSelected);
	    positionsDetails.add(lastSelected);
	    positionsDetails.add(allSelected);
	    
	    // positionnement dans le cercle...
	    positionsDetails.setSize(positionsDetails.getPreferredSize());
	    positionsDetails.setLocation((int) (cx-positionsDetails.getWidth()/2), (int) (cy-positionsDetails.getHeight()/2));
	    positionsPanel.add(positionsDetails);
	    
	    // bouton de validation
	    JButton layoutExtensionButton = new JButton("Extend selection from selected directions");
	    layoutExtensionButton.setAlignmentX(Component.CENTER_ALIGNMENT);
	    layoutExtensionButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				ArrayList<String> directionList = new ArrayList<String>();
				for(int i = 0; i < directions.length; i++)
				{
					if (directions[i].isSelected())
					{
						directionList.add(directionName[i]);
					}
				}
				
				String startPoint = "";
				
				if(firstSelected.isSelected()){
					startPoint = "first";
				} else if(lastSelected.isSelected()) {
					startPoint = "last";
				} else if(allSelected.isSelected()) {
					startPoint = "all";
				}
				
				LayoutSelection ls = new LayoutSelection(directionList, startPoint);
				
				layoutExtension(ls);
			}
			
		});

	    layoutExtensionPanel.add(layoutExtensionButton);
		
		//layoutExtensionPanel.add(aroundExtensionPanel);
		
		this.selectionDetailsContainer.add(layoutExtensionPanel);
		
		JPanel secondDetailsContainer = new JPanel();
		secondDetailsContainer.setLayout(new BoxLayout(secondDetailsContainer, BoxLayout.Y_AXIS));

		
		JPanel parentExtensionPanel = new JPanel();
		parentExtensionPanel.setBorder(BorderFactory.createTitledBorder("Parent Extension"));
		ImageIcon parentext = new ImageIcon("icons/parentext.png");
		JButton parentExtensionButton = new JButton(parentext);
		parentExtensionButton.setToolTipText("Extend selection to parent container");
		parentExtensionButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				parentExtension();
			}
			
		});
		parentExtensionPanel.add(parentExtensionButton);
		secondDetailsContainer.add(parentExtensionPanel);
		
		JPanel taskExtensionPanel =  new JPanel();
		taskExtensionPanel.setBorder(BorderFactory.createTitledBorder("Task Extension"));
		ImageIcon tasktext = new ImageIcon("icons/taskext.gif");
		JButton taskExtensionButton = new JButton(tasktext);
		taskExtensionButton.setToolTipText("Extend selection from attached task");
		
		taskExtensionButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				taskExtension();
			}
			
		});
		taskExtensionPanel.add(taskExtensionButton);
		secondDetailsContainer.add(taskExtensionPanel);
		
		JPanel functionalityExtensionPanel =  new JPanel();
		functionalityExtensionPanel.setBorder(BorderFactory.createTitledBorder("Functionality Extension"));
		ImageIcon functext = new ImageIcon("icons/funcext.png");
		JButton functionalityExtensionButton = new JButton(functext);
		functionalityExtensionButton.setToolTipText("Extend selection from attached functionality");
		functionalityExtensionButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				functionalityExtension();
			}
			
		});
		functionalityExtensionPanel.add(functionalityExtensionButton);
		secondDetailsContainer.add(functionalityExtensionPanel);
		
		/*
		// en attente d'implem
		JPanel conceptExtensionPanel =  new JPanel();
		conceptExtensionPanel.setBorder(BorderFactory.createTitledBorder("Concept Extension"));
		String[] conceptListData = { "Concept 1", "Concept 2" };
		JList conceptList = new JList(conceptListData);
		conceptList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		conceptList.setLayoutOrientation(JList.VERTICAL);
		JScrollPane listScroller = new JScrollPane(conceptList);
		
		conceptExtensionPanel.add(listScroller);
		conceptExtensionPanel.add(new JButton("Extend selection from selected concept"));
		
		secondDetailsContainer.add(conceptExtensionPanel);
		*/
		secondDetailsContainer.add(Box.createVerticalGlue());
		
		this.selectionDetailsContainer.add(secondDetailsContainer);
		
		selectionToolsBar.add(Box.createVerticalStrut(5));
		selectionToolsBar.add(this.selectionDetailsContainer);
		
		ActionListener creation = new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				addNewScreen();
				
			}
		};
		
		forExtraction = new ScreenPossibilities(true, creation, true, this);
		forExtraction.setButtonMessage("extract to");
		forExtraction.init();
		
		selectionToolsBar.add(Box.createVerticalStrut(5));
		selectionToolsBar.add(forExtraction);
		
		/* Modification for selection help */
		this.guideCheckBox.addItemListener(new ItemListener() {

			@Override
			public void itemStateChanged(ItemEvent e) {
				// TODO Auto-generated method stub
				if(e.getStateChange() == ItemEvent.SELECTED) {
					setToolsEnable(false, selectionDetailsContainer);
//					setToolsEnable(false, extractionDetailsContainer);
					guideTypesList.setEnabled(true);
					changeGuideState(true);
				}
				
				if(e.getStateChange() == ItemEvent.DESELECTED) {
					setToolsEnable(true, selectionDetailsContainer);
//					setToolsEnable(true, extractionDetailsContainer);
					guideTypesList.setEnabled(false);
					changeGuideState(false);
				}
			}
			
		});
		
//		selectionToolsBar.add(this.extractionDetailsContainer);
		
		

		selectionToolsBar.add(Box.createVerticalGlue());
		

		
		this.setToolsEnable(false);
	}
	
	public void setToolsEnable(Boolean enabled) {
		this.setToolsEnable(enabled, this.toolsContainer);
		
		if(enabled){
			this.setToolsEnable(enabled, this.guideSelectionPanel);
			
			this.guideTypesList.setEnabled(this.guideCheckBox.isSelected());
			
			this.setToolsEnable(!this.guideCheckBox.isSelected(), this.selectionDetailsContainer);
			
//			this.setToolsEnable(!this.guideCheckBox.isSelected(), this.extractionDetailsContainer);
			this.setToolsEnable(!this.guideCheckBox.isSelected(), this.forExtraction);
			
		} else {
			this.setToolsEnable(enabled, this.guideSelectionPanel);
			
			this.setToolsEnable(enabled, this.selectionDetailsContainer);
			
//			this.setToolsEnable(enabled, this.extractionDetailsContainer);
			this.setToolsEnable(enabled, this.forExtraction);
		}
	}
	
	private void setToolsEnable(Boolean enabled, JPanel container) {
		for(Component c: container.getComponents()) {
			if(c instanceof JPanel) {
				this.setToolsEnable(enabled, (JPanel) c);
			} else {
				c.setEnabled(enabled);
			}
		}
	}
	
	private void changeSelectionType(SelectionType selectionType) {
		this.setChanged();
		this.notifyObservers(selectionType);
	}
	
	private void changeGuideType(GuideType guideType) {
		this.setChanged();
		this.notifyObservers(guideType);
	}
	
	private void changeGuideState(Boolean enabled) {
		this.setChanged();
		this.notifyObservers(enabled);
	}
	
	private void clearSelection() {
		this.setChanged();
		this.notifyObservers("clear");
	}
	
	private void selectAll() {
		this.setChanged();
		this.notifyObservers("all");
	}
	
	private void parentExtension() {
		this.setChanged();
		this.notifyObservers("parentExtension");
	}
	
	private void taskExtension() {
		this.setChanged();
		this.notifyObservers("taskExtension");
	}
	
	private void functionalityExtension() {
		this.setChanged();
		this.notifyObservers("functionalityExtension");
	}
	
	private void layoutExtension(LayoutSelection ls) {
		this.setChanged();
		this.notifyObservers(ls);
	}
	
	public void updateScreensList(ArrayList<Screen> screens) {
		/*
		screenComboBox.removeAllItems();
		for(Screen s: screens) {
			screenComboBox.addItem(s);
		}
		*/
		forExtraction.updateScreensList(screens);
		
	}
	
	public void addNewScreen() {
		String screenName = "New Screen";
		
		String s = (String)JOptionPane.showInputDialog(
                this.selectionToolsBar,
                "Screen Name:",
                "Screen Name Choice",
                JOptionPane.PLAIN_MESSAGE,
                null,
                null,
                "New Screen");

			//If a string was returned, say so.
			if ((s != null) && (s.length() > 0)) {
				screenName = s;
			}
		
		this.setChanged();
		this.notifyObservers(new ScreenInfo(screenName));
	}
	
	public void consume(Screen destination) {
		// Screen destination = (Screen) screenComboBox.getSelectedItem();
		
		this.setChanged();
		this.notifyObservers(destination);
		System.out.println(layoutExtensionPanel.getSize());

	}
}
